package com.atguigu.gmall.order.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.atguigu.gmall.common.constant.MqConst;
import com.atguigu.gmall.common.service.RabbitService;
import com.atguigu.gmall.common.util.HttpClientUtil;
import com.atguigu.gmall.model.enums.OrderStatus;
import com.atguigu.gmall.model.enums.PaymentStatus;
import com.atguigu.gmall.model.enums.PaymentWay;
import com.atguigu.gmall.model.enums.ProcessStatus;
import com.atguigu.gmall.model.order.OrderDetail;
import com.atguigu.gmall.model.order.OrderInfo;
import com.atguigu.gmall.order.mapper.OrderDetailMapper;
import com.atguigu.gmall.order.mapper.OrderInfoMapper;
import com.atguigu.gmall.order.service.OrderService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Service
public class OrderServiceImpl extends ServiceImpl<OrderInfoMapper,OrderInfo> implements OrderService {

    @Autowired
    private OrderInfoMapper orderInfoMapper;
    @Autowired
    private OrderDetailMapper orderDetailMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private RabbitService rabbitService;

    @Value("${ware.url}")
    private String WARE_URL;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long saveOrderInfo(OrderInfo orderInfo) {
        //orderInfo里面有orderDetailList
        orderInfo.sumTotalAmount();
        orderInfo.setOrderStatus(OrderStatus.UNPAID.name());
        orderInfo.setPaymentWay(PaymentWay.ONLINE.name());
        String outTradeNo = "ATGUIGU" + System.currentTimeMillis() + "" + new Random().nextInt(1000);
        orderInfo.setOutTradeNo(outTradeNo);
//        可以将商品的名称进行拼接！
        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
        StringBuilder sb = new StringBuilder();
        for (OrderDetail orderDetail : orderDetailList) {
            //  拼接商品的名称
            sb.append(orderDetail.getSkuName());
        }
        //  截取字符串！
        if (sb.length()>200){
            orderInfo.setTradeBody(sb.substring(0,200));
        }else {
            orderInfo.setTradeBody(sb.toString());
        }
        orderInfo.setCreateTime(new Date());
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE,1);
        //  过期时间 + 1 天
        orderInfo.setExpireTime(calendar.getTime());
        //  设置进度状态(未支付)
        orderInfo.setProcessStatus(ProcessStatus.UNPAID.name());
        orderInfoMapper.insert(orderInfo);

        //  保存orderDetail!先得到订单明细的集合
        List<OrderDetail> orderDetailLists = orderInfo.getOrderDetailList();
        for (OrderDetail orderDetail : orderDetailLists) {
            orderDetail.setOrderId(orderInfo.getId());
            // create_time
            orderDetail.setCreateTime(new Date());
            orderDetailMapper.insert(orderDetail);
        }
        Long orderId = orderInfo.getId();
        rabbitService.sendDelayMessage(MqConst.EXCHANGE_DIRECT_ORDER_CANCEL,MqConst.ROUTING_ORDER_CANCEL,orderId,MqConst.DELAY_TIME);
        return orderId;
    }

    /**
     * 生产流水号
     * @param userId
     * @return
     */
    @Override
    public String getTradeNo(String userId) {
// 定义key
        String tradeNoKey = "user:" + userId + ":tradeCode";
        // 定义一个流水号
        String tradeNo = UUID.randomUUID().toString().replace("-", "");

        redisTemplate.opsForValue().set(tradeNoKey,tradeNo);
        return tradeNo;
    }

    /**
     * 比较流水号
     * @param userId 获取缓存中的流水号
     * @param tradeCodeNo   页面传递过来的流水号
     * @return
     */
    @Override
    public boolean checkTradeCode(String userId, String tradeCodeNo) {
        // 定义key
        String tradeNoKey = "user:" + userId + ":tradeCode";
        String redisTradeNo = (String) redisTemplate.opsForValue().get(tradeNoKey);
        return tradeCodeNo.equals(redisTradeNo);
    }

    /**
     * 删除流水号
     * @param userId
     */
    @Override
    public void deleteTradeNo(String userId) {
        // 定义key
        String tradeNoKey = "user:" + userId + ":tradeCode";
        // 删除数据
        redisTemplate.delete(tradeNoKey);

    }

    /**
     * 验证库存
     * @param skuId
     * @param skuNum
     * @return
     */
    @Override
    public boolean checkStock(Long skuId, Integer skuNum) {

        // 远程调用http://localhost:9001/hasStock?skuId=10221&num=2
        String result = HttpClientUtil.doGet(WARE_URL + "/hasStock?skuId=" + skuId + "&num=" + skuNum);
        return "1".equals(result);

    }

    /**
     *根据订单id，关闭未支付订单
     * @param orderId
     */
    @Override
    public void execExpiredOrder(Long orderId) {
        //方式一
//        OrderInfo orderInfo = new OrderInfo();
//        orderInfo.setId(orderId);
//        orderInfo.setOrderStatus(OrderStatus.CLOSED.name());
//        orderInfo.setProcessStatus(ProcessStatus.CLOSED.name());
//        orderInfoMapper.updateById(orderInfo);

        // orderInfo
        this.updateOrderStatus(orderId, ProcessStatus.CLOSED);
        //发送一个消息通知payment，关闭paymentinfo
        this.rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_PAYMENT_CLOSE,MqConst.ROUTING_PAYMENT_CLOSE,orderId);
    }


    /**
     * 更改订单状态
     * @param orderId
     * @param processStatus
     */
    @Override
    public void updateOrderStatus(Long orderId, ProcessStatus processStatus) {
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setId(orderId);
        orderInfo.setProcessStatus(processStatus.name());
        orderInfo.setOrderStatus(processStatus.getOrderStatus().name());
        orderInfoMapper.updateById(orderInfo);
    }

    /**
     * 根据订单Id 查询订单信息
     * @param orderId
     * @return
     */
    @Override
    public OrderInfo getOrderInfo(Long orderId) {
        OrderInfo orderInfo = orderInfoMapper.selectById(orderId);
        QueryWrapper<OrderDetail> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("order_id", orderId);
        List<OrderDetail> orderDetailList = orderDetailMapper.selectList(queryWrapper);
        orderInfo.setOrderDetailList(orderDetailList);
        return orderInfo;
    }

    /**
     * 发送消息给库存！让仓库减库存
     * @param orderId
     */
    @Override
    public void sendOrderStatus(Long orderId) {
        if (orderId!=null) {
            this.updateOrderStatus(orderId, ProcessStatus.WAITING_DELEVER);
            //调用一个发送的方法，json串
            String  wareJson = this.initWareOrder(orderId);
            rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_WARE_STOCK,MqConst.ROUTING_WARE_STOCK,wareJson);
        }
    }

    /**
     * 返回jsonzifuc
     * @param orderId
     * @return
     */
    private String initWareOrder(Long orderId) {
        // Json 字符串是由orderInfo ，orderDetail 部分字段组成！
        OrderInfo orderInfo = this.getOrderInfo(orderId);
        //  将 orderInfo 中部分属性变为Json 字符串！
        Map map = this.initWareOrder(orderInfo);
        //  JSON.toJSONString(orderInfo); 不能这么转！
        return JSON.toJSONString(map);
    }

    /**
     * 将orderInfo 转换为Map集合
     * @param orderInfo
     * @return
     */
    @Override
    public Map initWareOrder(OrderInfo orderInfo){
        Map map = new HashMap();
        map.put("orderId",orderInfo.getId());
        map.put("consignee", orderInfo.getConsignee());
        map.put("consigneeTel", orderInfo.getConsigneeTel());
        map.put("orderComment", orderInfo.getOrderComment());
        map.put("orderBody", orderInfo.getTradeBody());
        map.put("deliveryAddress", orderInfo.getDeliveryAddress());
        map.put("paymentWay", "2");
        map.put("wareId", orderInfo.getWareId());// 仓库Id ，减库存拆单时需要使用！
        //  details:[{skuId:101,skuNum:1,skuName:’小米手64G’},{skuId:201,skuNum:1,skuName:’索尼耳机’}]
        //  数据来源于orderDetailList
        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
        //  声明一个集合来存储订单明细需要的数据！
        ArrayList<Map> maps = new ArrayList<>();
        //  循环遍历订单明细！
        for (OrderDetail orderDetail : orderDetailList) {
            HashMap<String, Object> details = new HashMap<>();
            details.put("skuId",orderDetail.getSkuId());
            details.put("skuNum",orderDetail.getSkuNum());
            details.put("skuName",orderDetail.getSkuName());
            //  将details 放入一个集合
            maps.add(details);
        }
        map.put("details",maps);
        return map;
    }
    /**
     * 拆单方法
     * @param orderId
     * @param wareSkuMap
     * @return
     */
    @Override
    public List<OrderInfo> orderSplit(String orderId, String wareSkuMap) {

        ArrayList<OrderInfo> orderInfoArrayList = new ArrayList<>();
    //  1.  先获取到原始订单 107
        OrderInfo orderInfo = this.getOrderInfo(Long.parseLong(orderId));
//        2.  将wareSkuMap 转换为我们能操作的对象 [{"wareId":"1","skuIds":["2","10"]},{"wareId":"2","skuIds":["3"]}]
//        3.  创建一个新的子订单 108 109 。。。
//        4.  给子订单赋值
//        5.  保存子订单到数据库
//        6.  修改原始订单的状态
//        7.  测试
        List<Map> maps = JSON.parseArray(wareSkuMap,Map.class);
        if (maps!=null){
            for (Map map : maps) {
                //获取库存id,商品Id
                String wareId = (String) map.get("wareId");
                List<String> skuIds = (List<String>) map.get("skuIds");
                OrderInfo subOrderInfo = new OrderInfo();
                // 属性拷贝
                BeanUtils.copyProperties(orderInfo,subOrderInfo);
                // 防止主键冲突
                subOrderInfo.setId(null);
                //父订单id
                subOrderInfo.setParentOrderId(Long.parseLong(orderId));
                // 赋值仓库Id
                subOrderInfo.setWareId(wareId);
                // 计算子订单的金额: 必须有订单明细
                // 获取到子订单明细
                // 声明一个集合来存储子订单明细
                ArrayList<OrderDetail> orderDetails = new ArrayList<>();
                List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
                if (orderDetailList != null && orderDetailList.size() > 0) {
                    for (OrderDetail orderDetail : orderDetailList) {
                        // 获取子订单明细的商品Id
                        for (String skuId : skuIds) {
                            if (Long.parseLong(skuId) == orderDetail.getSkuId().longValue()) {
                                // 将订单明细添加到集合
                                orderDetails.add(orderDetail);

                            }
                        }
                    }
                }
                subOrderInfo.setOrderDetailList(orderDetails);
                // 计算总金额
                subOrderInfo.sumTotalAmount();
                // 保存子订单
                saveOrderInfo(subOrderInfo);
                // 将子订单添加到集合中！
                orderInfoArrayList.add(subOrderInfo);
            }
        }

        // 修改原始订单的状态
        this.updateOrderStatus(Long.parseLong(orderId), ProcessStatus.SPLIT);
        return orderInfoArrayList;

    }
    /**
     *关闭过期订单
     * @param orderId
     * @param flag
     */
    @Override
    public void execExpiredOrder(Long orderId, String flag) {
        // 调用方法 状态
        updateOrderStatus(orderId,ProcessStatus.CLOSED);
        if ("2".equals(flag)){
            // 发送消息队列，关闭支付宝的交易记录。
            rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_PAYMENT_CLOSE,MqConst.ROUTING_PAYMENT_CLOSE,orderId);
        }

    }
}
